﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using DBUtility.PetaPoco;
using System.Data;

namespace DAL
{
    /// <summary>
    /// 数据访问基类(泛型约束，必须是类，必须有无参构造函数，子类只需继承而已)
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class BaseDAL<T> where T : class, new()
    {
        protected readonly Database db = Database.db;

        #region 是否存在该记录
        /// <summary>
        /// 是否存在该记录
        /// </summary>
        /// <param name="isSuccess">执行是否成功(输出) true=成功 false=失败</param>
        /// <param name="primaryKeyValue">主键值</param>
        /// <returns>true=存在 false=不存在</returns>
        public virtual bool Exists(out bool isSuccess, object primaryKeyValue)
        {
            try
            {                
                bool exists = db.Exists<T>(primaryKeyValue);
                isSuccess = true;
                return exists;
            }
            catch
            {
                isSuccess = false;
                return false;
            }
        }

        /// <summary>
        /// 是否存在该记录
        /// </summary>
        /// <param name="isSuccess">执行是否成功(输出) true=成功 false=失败</param>
        /// <param name="strSql">sql语句或条件</param>
        /// <param name="paraList">where条件参数列表</param>
        /// <returns>true=存在 false=不存在</returns>
        public virtual bool Exists(out bool isSuccess, string strSql, params object[] paraList)
        {
            var pd = DBUtility.PetaPoco.Database.PocoData.ForType(typeof(T));
            StringBuilder sbSql = new StringBuilder(100);
            
            if (strSql.IndexOf("select", StringComparison.OrdinalIgnoreCase) == -1)
            {
                if (!string.IsNullOrEmpty(pd.TableInfo.PrimaryKey))
                {
                    sbSql.Append("select count(" + pd.TableInfo.PrimaryKey + ")");
                }
                else
                {
                    sbSql.Append("select count(*)");
                }
            }

            if (strSql.IndexOf("from", StringComparison.OrdinalIgnoreCase) == -1)
            {
                sbSql.Append(" from " + pd.TableInfo.TableName + " ");
            }            
            sbSql.Append(strSql);

            try
            {

                var obj = db.ExecuteScalar(sbSql.ToString(), paraList);
                isSuccess = true;

                if (obj != null && obj != DBNull.Value)
                {
                    return true;
                }
                return false;
            }
            catch
            {
                isSuccess = false;
                return false;
            }
        }
        #endregion

        #region 添加
        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="model">实体对象</param>
        /// <returns>主键值 0=出错</returns>
        public virtual int Add(T model)
        {
            object objId = null;
            try
            {
                objId = db.Insert(model);
            }
            catch(Exception ex)
            {
                return 0;
            }

            if (objId != null && objId != DBNull.Value)
            {
                int id;
                if (int.TryParse(objId.ToString(), out id))
                {
                    return id;
                }
                else
                {
                    return 0;
                }
            }
            return 0;
        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="model">实体对象</param>
        /// <returns>true=成功 false=出错</returns>
        public virtual bool AddReturnBool(T model)
        {
            object objIsSuccess = null;
            try
            {
                objIsSuccess = db.Insert(model);
            }
            catch
            {
                return false;
            }

            if (objIsSuccess != null && objIsSuccess != DBNull.Value)
            {
                bool isSuccess;
                if (bool.TryParse(objIsSuccess.ToString(), out isSuccess))
                {
                    return isSuccess;
                }
                else
                {
                    return false;
                }
            }
            return false;
        }
        #endregion

        #region 修改
        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="model">实体对象</param>
        /// <returns>受影响的行数 -1=出错</returns>
        public virtual int Update(T model)
        {
            try
            {
                return db.Update(model);
            }
            catch
            {
                return -1;
            }
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="type">实体类</param>
        /// <param name="model">实体对象(包含主键值)</param>
        /// <returns>受影响的行数 -1=出错</returns>
        public virtual int Update(Type type, object model)
        {
            try
            {
                var pd = DBUtility.PetaPoco.Database.PocoData.ForType(type);
                return db.Update(pd.TableInfo.TableName, pd.TableInfo.PrimaryKey, model);
            }
            catch
            {
                return -1;
            }
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="type">实体类</param>
        /// <param name="model">实体对象(不包含主键值)</param>
        /// <param name="primaryKeyValue">主键值</param>
        /// <returns>受影响的行数 -1=出错</returns>
        public virtual int Update(Type type, object model, object primaryKeyValue)
        {
            try
            {
                var pd = DBUtility.PetaPoco.Database.PocoData.ForType(type);
                return db.Update(pd.TableInfo.TableName, pd.TableInfo.PrimaryKey, model, primaryKeyValue);
            }
            catch
            {
                return -1;
            }
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="primaryKeyName">主键名</param>
        /// <param name="model">实体对象</param>
        /// <param name="primaryKeyValue">主键值</param>
        /// <returns>受影响的行数 -1=出错</returns>
        public virtual int Update(string tableName, string primaryKeyName, object model, object primaryKeyValue)
        {
            try
            {
                return db.Update(tableName, primaryKeyName, model, primaryKeyValue);
            }
            catch
            {
                return -1;
            }
        }
        #endregion

        #region 删除
        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="model">实体对象</param>
        /// <returns>受影响的行数 -1=出错</returns>
        public virtual int Delete(T model)
        {
            try
            {
                return db.Delete(model);
            }
            catch
            {
                return -1;
            }
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="primaryKeyValue">主键值</param>
        /// <returns>受影响的行数 -1=出错</returns>
        public virtual int Delete<T>(object primaryKeyValue)
        {
            try
            {
                return db.Delete<T>(primaryKeyValue);
            }
            catch
            {
                return -1;
            }
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="strSql">sql语句或where语句</param>
        /// <param name="paraList">where条件参数列表</param>
        /// <returns>受影响的行数 -1=出错</returns>
        public virtual int Delete<T>(string strSql, params object[] paraList)
        {
            try
            {
                return db.Delete<T>(strSql, paraList);
            }
            catch
            {
                return -1;
            }
        }
        #endregion

        #region 获取实体
        /// <summary>
        /// 获取实体
        /// </summary>
        /// <param name="isSuccess">执行是否成功(输出) true=成功 false=失败</param>
        /// <param name="primaryKeyValue">主键值</param>        
        /// <returns>实体对象</returns>
        public virtual T GetModel(out bool isSuccess, object primaryKeyValue)
        {
            T model = null;
            try
            {
                model = db.SingleOrDefault<T>(primaryKeyValue);
                isSuccess = true;                
            }
            catch
            {
                isSuccess = false;
            }
            return model;
        }

        /// <summary>
        /// 获取实体
        /// </summary>
        /// <param name="isSuccess">执行是否成功(输出) true=成功 false=失败</param>
        /// <param name="strSql">sql语句或where语句</param>
        /// <param name="paraList">where条件参数列表</param>
        /// <returns>实体对象</returns>
        public virtual T GetModel(out bool isSuccess, string strSql, params object[] paraList)
        {
            T model = null;
            try
            {
                model= db.FirstOrDefault<T>(strSql, paraList);
                isSuccess = true;
            }
            catch
            {
                isSuccess = false;
            }
            return model;
        }
        #endregion

        #region 获取列表
        /// <summary>
        /// 获取列表
        /// </summary>
        /// <param name="isSuccess">执行是否成功(输出) true=成功 false=失败</param>
        /// <param name="strSql">sql语句或where语句</param>
        /// <param name="paraList">where条件参数列表</param>        
        /// <returns>实体对象列表 null=出错</returns>
        public virtual List<T> GetList(string strSql, params object[] paraList)
        {
            List<T> list = null;
            try
            {
                list = db.Fetch<T>(strSql, paraList);
                return list;
            }
            catch 
            {
            
            }
            return list;
        }
        #endregion

        #region 获取分页列表
        /// <summary>
        /// 获取分页列表
        /// </summary>
        /// <param name="isSuccess">执行是否成功(输出) true=成功 false=失败</param>
        /// <param name="pageIndex">页索引</param>
        /// <param name="pageSize">页大小</param>
        /// <param name="strSql">sql语句或where语句</param>
        /// <param name="totalCount">总记录数(输出)</param>
        /// <param name="paraList">where条件参数列表</param>        
        /// <returns>实体对象列表 null=出错</returns>
        public virtual List<T> GetPagedList(uint pageIndex, ushort pageSize, string strSql, out uint totalCount, params object[] paraList)
        {
            try
            {
                Page<T> page = db.Page<T>(pageIndex, pageSize, strSql, paraList);
                totalCount = (uint)page.TotalItems;
                return page.Items;
            }
            catch
            {
                totalCount = 0;
                return null;
            }
        }
        #endregion

        #region 获取首行首列值
        /// <summary>
        /// 获取首行首列值
        /// </summary>
        /// <param name="isSuccess">执行是否成功(输出) true=成功 false=失败</param>
        /// <param name="strSql">sql语句或where语句</param>
        /// <param name="paraList">where条件参数列表</param>
        /// <returns>实体对象</returns>
        public virtual T GetSingle(out bool isSuccess, string strSql, params object[] paraList)
        {
            T model = null;
            try
            {
                model = db.Single<T>(strSql, paraList);
                isSuccess = true;
            }
            catch
            {
                isSuccess = false;
            }
            return model;
        } 
        #endregion

        #region 执行Sql语句
        /// <summary>
        /// 执行Sql
        /// </summary>
        /// <param name="strSql">sql语句或where语句</param>
        /// <param name="paraList">where条件参数列表</param>
        /// <returns>受影响的行数 -1=出错</returns>
        public virtual uint Execute(string strSql, params object[] paraList)
        {
            try
            {
                return (uint)db.Execute(strSql, paraList);
            }
            catch
            {
                return 0;
            }
        }

        /// <summary>
        /// 获取DataTable
        /// </summary>
        /// <param name="strSql">sql语句或where语句</param>
        /// <param name="paraList">where条件参数列表</param>
        /// <returns>DataTable null=出错</returns>
        public virtual DataTable GetDataTable(string strSql, params object[] paraList)
        {
            try
            {
                return db.GetDataTable(strSql, paraList);
            }
            catch
            {
                return null;
            }
        }
        #endregion
    }
}
